﻿/*-----------------------------------------------
// File: EngineMsgCallback.cs
// Description: 
// Author: Shaobing	492057342@qq.com
-----------------------------------------------*/
using UnityEngine;
using System.Collections;
using Battle.Engine;
using ProtoBuf.Message;
using Battle.Engine.LogicModel;
using System.Collections.Generic;

namespace Battle.Communication
{
    public class EngineMsgCallback : EngineCallback 
    {
        public EngineData engineData;
        public void Send(BattlePacket bp) {
            Battle.BattleMsgCtrl.GetInstance().msgCtrl.EngineSend(bp);
        }
        public void Send(int opcode, object msg) {
            var bp = new BattlePacket();
            bp.opcode = opcode;
            bp.kBody = msg;
            Send(bp);
        }

        //战斗开始
        public override void BattleBegin(CampType roundCamp)
        {
            SCFightStart msg = new SCFightStart();
            msg.initRunCamp = (int)roundCamp;
            Send(OpDefine.SCFightStart, msg);
        }

        //战斗结束,战斗结果
        public override void BattleEnd(EngineData data)
        {
            BattleEndCalc calc = new BattleEndCalc();
            calc.Init(BattleManager.Instance.battleData.battleType, BattleCamp.Attacker, data);
            bool isAttackerWin = calc.CheckResult();
            SCAttackResult msg = new SCAttackResult();
            msg.isSuccess = isAttackerWin ? 1 : 0;
            Send(OpDefine.SCAttackResult, msg);
        }

        public override void RoundBegin(int roundNum, CampType roundCamp, EngineData data)
        {
            SCNewRound msg = new SCNewRound();
            msg.roundNum = roundNum;
            msg.attacker = new OneFighter();
            msg.attacker.camp = (int)data.attacker.camp;
            msg.attacker.angerNum = data.attacker.angerNum;
            msg.attacker.maxAngerNum = data.attacker.maxAngerNum;
            foreach (var actor in data.attacker.actors) {
                ProtoBuf.Message.Actor _actor = new Actor();
                _actor.uid = actor.uniqueId;
                _actor.heroId = actor.heroId;
                _actor.hp = actor.attribute.hp;
                _actor.maxhp = actor.attribute.maxHp;
                _actor.level = 1;
                _actor.weaponId = "";
                _actor.FPId = actor.MainPosition.ToFPID();
                foreach (var skill in actor.skills) {
                    ProtoBuf.Message.ActorSkill _skill = new ActorSkill();
                    _skill.HSId = skill.id;
                    _skill.skillType = skill.index;
                    _skill.level = 1;
                    _skill.cd = skill.cooldown;
                    _skill.cancast = actor.isSkillReady(skill) ? 1 : 0; 
                    _actor.skills.Add(_skill);
                }
                foreach (var buff in actor.buffManager.buffs) {
                    if (buff.onceData)
                        continue;
                    ProtoBuf.Message.Buffer _buff = new Buffer();
                    _buff.uid = buff.uniqueId;
                    _buff.bufferId = buff.id;
                    _buff.sourceUid = buff.buffOrigion.GetSourceUniqueId();
                    _buff.targetUid = buff.buffTargetActor.uniqueId;
                    _actor.buffers.Add(_buff);
                }
                msg.attacker.actors.Add(_actor);
            }

            msg.defender = new OneFighter();
            msg.defender.camp = (int)data.defender.camp;
            msg.defender.angerNum = data.defender.angerNum;
            msg.defender.maxAngerNum = data.defender.maxAngerNum;
            foreach (var actor in data.defender.actors)
            {
                ProtoBuf.Message.Actor _actor = new Actor();
                _actor.uid = actor.uniqueId;
                _actor.heroId = actor.heroId;
                _actor.hp = actor.attribute.hp;
                _actor.maxhp = actor.attribute.maxHp;
                _actor.level = 1;
                _actor.weaponId = "";
                _actor.FPId = actor.MainPosition.ToFPID();
                foreach (var skill in actor.skills)
                {
                    ProtoBuf.Message.ActorSkill _skill = new ActorSkill();
                    _skill.HSId = skill.id;
                    _skill.skillType = skill.index;
                    _skill.level = 1;
                    _skill.cd = skill.cooldown;
                    _skill.cancast = actor.isSkillReady(skill) ? 1 : 0; 
                    _actor.skills.Add(_skill);
                }
                foreach (var buff in actor.buffManager.buffs)
                {
                    ProtoBuf.Message.Buffer _buff = new Buffer();
                    _buff.uid = buff.uniqueId;
                    _buff.bufferId = buff.id;
                    _buff.sourceUid = buff.buffOrigion.GetSourceUniqueId();
                    _buff.targetUid = buff.buffTargetActor.uniqueId;
                    _actor.buffers.Add(_buff);
                }
                msg.defender.actors.Add(_actor);
            }
            Send(OpDefine.SCNewRound, msg);
        }

        public override void RoundEnd(CampType nextRoundCamp)
        {
            SCRoundOver msg = new SCRoundOver();
            msg.nextRoundRunCamp = (int)nextRoundCamp;
            Send(OpDefine.SCRoundOver, msg);
        }

        public override void SkillBegin(FSkill skill, List<FActor> targets)
        {
            if (skill.IsUltimate)
            {
                SCUltimateCastBegin msg = new SCUltimateCastBegin();
                msg.actorUid = skill.actor.uniqueId;
                msg.camp = (int)skill.actor.player.camp;
                foreach (var target in targets) {
                    msg.targetUids.Add(target.uniqueId);
                }
                Send(OpDefine.SCUltimateCastBegin, msg);
            }
            else {
                SCSkillCast msg = new SCSkillCast();
                msg.actorUid = skill.actor.uniqueId;
                msg.camp = (int)skill.actor.player.camp;
                msg.skillType = skill.index;
                msg.FPId = skill.target.position.ToFPID();
                msg.targetCamp = (int)skill.target.player.camp;
                msg.needMove = skill.needMove;
                Send(OpDefine.SCSkillCast, msg);
            }
        }

        public override void SkillPress(CampType camp, string uniquedId, int skillIndex)
        {
            SCSkillPress msg = new SCSkillPress();
            msg.camp = (int)camp;
            msg.actorUid = uniquedId;
            msg.skillType = skillIndex;
            Send(OpDefine.SCSkillPress, msg);
        }

        public override void SkillEnd(CampType camp, string uniquedId, int skillIndex, FSkill skill)
        {
            //int aa = 0;
        }

        public override void SkillCast(Engine.LogicModel.FRelease release)
        {
            //SCTickExport msg = new SCTickExport();
            //OnceCast cast = new OnceCast();
            //cast.skillOnceCasts = new SkillOnceCast();
            //cast.skillOnceCasts.sourceUid = release.cast.actor.uniqueId;
            //cast.skillOnceCasts.skillType = release.cast.skill.index;
            //cast.skillOnceCasts.releaseId = release.cast.id;
            //cast.skillOnceCasts.roundNum = release.cast.actor.player.engineData.roundNum; 
            //cast.skillOnceCasts.comboInfo = new ComboInfo();
            //cast.skillOnceCasts.comboInfo.camp = (int)release.cast.actor.player.camp;
            //cast.skillOnceCasts.comboInfo.comboNum = 15;
            //cast.skillOnceCasts.exportMsg = new PropExport();
            //HpExport hpExport = new HpExport();
            //hpExport.targetUid = release.cast.skill.target.uniqueId;
            //hpExport.hpExportNum = -15;
            //hpExport.specialType = 0;
            //cast.skillOnceCasts.exportMsg.hpExports.Add(hpExport);
            //cast.skillOnceCasts.exportMsg.createMsg = new CreateMsg();
            //cast.skillOnceCasts.exportMsg.destroyObjs = new DestroyObj();
            //msg.tickOnceCasts.Add(cast);

            //Send(OpDefine.SCTickExport, msg);
        }

        public override void SkillProject(Engine.LogicModel.FRelease release)
        {
            SCShoot msg = new SCShoot();
            msg.actorUid = release.cast.skill.actor.uniqueId;
            msg.camp = (int)release.cast.skill.actor.player.camp;
            msg.releaseSkillType = release.cast.skill.index;
            msg.releaseId = release.cast.id;
            msg.FPId = release.cast.skill.target.position.ToFPID();
            msg.targetCamp = (int)release.cast.skill.actor.player.enemyCamp;
            msg.roundNum = release.cast.skill.actor.player.engineData.roundNum;

            Send(OpDefine.SCShoot, msg);

            //Send(OpDefine.SCShoot, msg);
        }

        List<OnceCast> ParseSCTickExport(List<FExport> exports) {
            List<OnceCast> onceCasts = new List<OnceCast>();

            foreach (var export in exports)
            {
                FExportOnceData od = (FExportOnceData)export;
                if (od.cast != null)
                {
                    OnceCast cast = new OnceCast();
                    cast.skillOnceCasts = new SkillOnceCast();
                    cast.skillOnceCasts.sourceUid = od.source.uniqueId;
                    cast.skillOnceCasts.skillType = od.cast.skill.index;
                    cast.skillOnceCasts.releaseId = od.cast.id;
                    cast.skillOnceCasts.roundNum = od.source.player.engineData.roundNum;
                    cast.skillOnceCasts.exportMsg = new PropExport();
                    foreach (var val in od.values)
                    {
                        switch (val.exportValClass)
                        {
                            case ExportValueClass.HP:
                                if (val.damageType == HpInfSpecialType.Rebound)
                                {
                                    RebornExport rExport = new RebornExport();
                                    rExport.targetUid = val.target.uniqueId;
                                    rExport.rebornHealHpNum = val.value;

                                    foreach (var s in val.target.skills)
                                    {
                                        ProtoBuf.Message.ActorSkill _skill = new ActorSkill();
                                        _skill.HSId = s.id;
                                        _skill.skillType = s.index;
                                        _skill.level = 1;
                                        _skill.cd = s.cooldown;
                                        _skill.cancast = val.target.isSkillReady(s) ? 1 : 0;
                                        rExport.skills.Add(_skill);
                                    }
                                    cast.skillOnceCasts.exportMsg.rebornExports.Add(rExport);
                                }
                                else {
                                    HpExport hpExport = new HpExport();
                                    hpExport.targetUid = val.target.uniqueId;
                                    hpExport.hpExportNum = val.value;
                                    hpExport.specialType = (int)val.damageType;
                                    cast.skillOnceCasts.exportMsg.hpExports.Add(hpExport);
                                }
                                break;
                            case ExportValueClass.ANGER:
                                AngerExport angerExport = new AngerExport();
                                angerExport.targetCamp = (int)val.target.player.camp;
                                angerExport.angerExportNum = val.value;
                                cast.skillOnceCasts.exportMsg.angerExports.Add(angerExport);
                                break;
                            case ExportValueClass.DOUBLE_HIT:
                                cast.skillOnceCasts.comboInfo = new ComboInfo();
                                cast.skillOnceCasts.comboInfo.camp = (int)val.target.player.camp;
                                cast.skillOnceCasts.comboInfo.comboNum = (int)val.value;
                                break;
                            case ExportValueClass.SPE_STATE:
                                SpecialStateExport specialStateExport = new SpecialStateExport();
                                specialStateExport.targetUid = val.target.uniqueId;
                                specialStateExport.specialState = (int)val.value;
                                specialStateExport.surplusTime = val.extraValue;
                                cast.skillOnceCasts.exportMsg.specialStateExports.Add(specialStateExport);
                                break;
                            case ExportValueClass.MAGIC_STONE:
                                FireMagicStoneExport magicStoneExport = new FireMagicStoneExport();
                                magicStoneExport.sourceUid = val.source.uniqueId;
                                magicStoneExport.targetUid = val.target.uniqueId;
                                magicStoneExport.stoneNum = (int)val.value;
                                cast.skillOnceCasts.exportMsg.fireMagicStoneExport.Add(magicStoneExport);
                                break;
                            case ExportValueClass.WATER_BALL:
                                AngerMagicStoneExport angerStoneExport = new AngerMagicStoneExport();
                                angerStoneExport.sourceUid = val.source.uniqueId;
                                angerStoneExport.stoneNum = (int)val.value;
                                cast.skillOnceCasts.exportMsg.angerMagicStoneExport.Add(angerStoneExport);
                                break;
                            default:
                                break;
                        }
                    }
                    //BUFF加载
                    cast.skillOnceCasts.exportMsg.createMsg = new CreateMsg();
                    foreach (var buff in od.loadBuffs)
                    {
                        cast.skillOnceCasts.exportMsg.createMsg.buffers.Add(buff.DataToClientModel());
                    }
                    //BUFF卸载
                    cast.skillOnceCasts.exportMsg.destroyObjs = new DestroyObj();
                    foreach (var buff in od.unloadBuffs)
                    {
                        cast.skillOnceCasts.exportMsg.destroyObjs.destroyBufferUids.Add(buff.uniqueId);
                    }
                    //角色死亡
                    foreach (var actor in od.deadActors)
                    {
                        cast.skillOnceCasts.exportMsg.destroyObjs.actorUids.Add(actor.uniqueId);
                    }
                    onceCasts.Add(cast);
                }
                else if (od.talent != null)
                {
                    OnceCast cast = new OnceCast();
                    cast.talentOnceCasts = new TalentOnceCast();
                    cast.talentOnceCasts.talentId = od.talent.id;
                    cast.talentOnceCasts.sourceUid = od.source.uniqueId;
                    cast.talentOnceCasts.roundNum = od.source.player.engineData.roundNum;
                    cast.talentOnceCasts.exportMsg = new PropExport();
                    //BUFF加载
                    cast.talentOnceCasts.exportMsg.createMsg = new CreateMsg();
                    foreach (var buff in od.loadBuffs)
                    {
                        cast.talentOnceCasts.exportMsg.createMsg.buffers.Add(buff.DataToClientModel());
                    }
                    //BUFF卸载
                    cast.talentOnceCasts.exportMsg.destroyObjs = new DestroyObj();
                    foreach (var buff in od.unloadBuffs)
                    {
                        cast.talentOnceCasts.exportMsg.destroyObjs.destroyBufferUids.Add(buff.uniqueId);
                    }
                    //角色死亡
                    foreach (var actor in od.deadActors)
                    {
                        cast.talentOnceCasts.exportMsg.destroyObjs.actorUids.Add(actor.uniqueId);
                    }
                    onceCasts.Add(cast);
                }
                else if (od.buff != null)
                {
                    OnceCast cast = new OnceCast();
                    cast.buffOnceCasts = new BuffOnceCast();
                    cast.buffOnceCasts.sourceUid = od.buff.uniqueId;
                    cast.buffOnceCasts.sourceBuffId = od.buff.id;
                    cast.buffOnceCasts.roundNum = od.source.player.engineData.roundNum;
                    cast.buffOnceCasts.exportMsg = new PropExport();
                    foreach (var val in od.values)
                    {
                        switch (val.exportValClass)
                        {
                            case ExportValueClass.HP:
                                if (val.damageType == HpInfSpecialType.Rebound)
                                {
                                    RebornExport rExport = new RebornExport();
                                    rExport.targetUid = val.target.uniqueId;
                                    rExport.rebornHealHpNum = val.value;

                                    foreach (var s in val.target.skills)
                                    {
                                        ProtoBuf.Message.ActorSkill _skill = new ActorSkill();
                                        _skill.HSId = s.id;
                                        _skill.skillType = s.index;
                                        _skill.level = 1;
                                        _skill.cd = s.cooldown;
                                        _skill.cancast = val.target.isSkillReady(s) ? 1 : 0;
                                        rExport.skills.Add(_skill);
                                    }
                                    cast.buffOnceCasts.exportMsg.rebornExports.Add(rExport);
                                }
                                else {
                                    HpExport hpExport = new HpExport();
                                    hpExport.targetUid = val.target.uniqueId;
                                    hpExport.hpExportNum = val.value;
                                    hpExport.specialType = (int)val.damageType;
                                    cast.buffOnceCasts.exportMsg.hpExports.Add(hpExport);
                                }
                                break;
                            case ExportValueClass.ANGER:
                                AngerExport angerExport = new AngerExport();
                                angerExport.targetCamp = (int)val.target.player.camp;
                                angerExport.angerExportNum = (int)val.value;
                                cast.buffOnceCasts.exportMsg.angerExports.Add(angerExport);
                                break;
                            case ExportValueClass.SPE_STATE:
                                SpecialStateExport specialStateExport = new SpecialStateExport();
                                specialStateExport.targetUid = val.target.uniqueId;
                                specialStateExport.specialState = (int)val.value;
                                specialStateExport.surplusTime = val.extraValue;
                                cast.buffOnceCasts.exportMsg.specialStateExports.Add(specialStateExport);
                                break;
                            default:
                                break;
                        }
                    }
                    //BUFF加载
                    cast.buffOnceCasts.exportMsg.createMsg = new CreateMsg();
                    foreach (var buff in od.loadBuffs)
                    {
                        cast.buffOnceCasts.exportMsg.createMsg.buffers.Add(buff.DataToClientModel());
                    }
                    //BUFF卸载
                    cast.buffOnceCasts.exportMsg.destroyObjs = new DestroyObj();
                    foreach (var buff in od.unloadBuffs)
                    {
                        cast.buffOnceCasts.exportMsg.destroyObjs.destroyBufferUids.Add(buff.uniqueId);
                    }
                    //角色死亡
                    foreach (var actor in od.deadActors)
                    {
                        cast.buffOnceCasts.exportMsg.destroyObjs.actorUids.Add(actor.uniqueId);
                    }
                    onceCasts.Add(cast);
                }
            }
            return onceCasts;
        }


        //
        public override void Tick(List<FExport> exports)
        {
            SCTickExport msg = new SCTickExport();
            msg.exportTimer = 0;
            msg.tickOnceCasts.AddRange(ParseSCTickExport(exports));
            Send(OpDefine.SCTickExport, msg);
        }

        public override void RoundBeginTick(List<FExport> exports)
        {
            SCTickExport msg = new SCTickExport();
            msg.exportTimer = 1;
            msg.tickOnceCasts.AddRange(ParseSCTickExport(exports));
            Send(OpDefine.SCTickExport, msg);
        }

        public override void RoundEndTick(List<FExport> exports)
        {
            SCTickExport msg = new SCTickExport();
            msg.exportTimer = 2;
            msg.tickOnceCasts.AddRange(ParseSCTickExport(exports));
            Send(OpDefine.SCTickExport, msg);
        }



        public override void BreakCombo(string playerUid)
        {
            SCComboBreak msg = new SCComboBreak();
            msg.fighterUid = playerUid;
            Send(OpDefine.SCComboBreak, msg);
        }

        public override void HaventActiveNormalSkill()
        {
            SCCanRoundOver msg = new SCCanRoundOver();
            Send(OpDefine.SCCanRoundOver, msg);
        }

        public override void TransConfirm(List<string> uids, List<int> fpids)
        {
            SCTransOver msg = new SCTransOver();
            for (int i = 0; i < uids.Count; ++i) {
                msg.actorUids.Add(uids[i]);
                msg.actorFPIds.Add(fpids[i]);
            }
            Send(OpDefine.SCTransOver, msg);
        }

        public override void SkipUltimate()
        {
            SCJumpUltimate msg = new SCJumpUltimate();
            Send(OpDefine.SCJumpUltimate, msg);
        }

    }
}